package main

import (
	"fmt"
)

/*
字符串的排列
给你两个字符串s1和s2 ，写一个函数来判断 s2 是否包含 s1的排列。如果是，返回 true ；否则，返回 false 。

换句话说，s1 的排列之一是 s2 的 子串 。

eg：
输入：s1 = "ab" s2 = "eidbaooo"
输出：true
解释：s2 包含 s1 的排列之一 ("ba").

输入：s1 = "ab" s2 = ""eidboaoo""
输出：false
解释：s2 包含 s1 的排列之一 ("boa").
*/

//自己写的铸币map滑动窗口解法
//func checkInclusion(s1, s2 string) bool {
//	if len(s1)> len(s2) {
//		return false
//	}
//	wd1 := make(map[byte]int, len(s1))
//	wd2 := make(map[byte]int, len(s1))
//	//将s1中每个元素存在map wd1中，k:v->字母:出现次数
//	for i := 0; i < len(s1); i++ {
//		wd1[s1[i]]++
//	}
//	var left, right = 0, len(s1)-1
//	//将s2前len(s)个元素添加到wd2中
//	for j := 0; j < len(s1); j++ {
//		wd2[s2[j]]++
//	}
//	for right<len(s2){
//		//判断两个map是否相同 如果相同 说明s1是s2字串
//		if reflect.DeepEqual(wd1,wd2)==true{
//			return true
//		//如果不同 滑动窗口继续比较
//		}else{
//			wd2[s2[left]]--
//			if wd2[s2[left]]==0{
//				delete(wd2,s2[left])
//			}
//			left++
//			right++
//			if right<len(s2){
//				wd2[s2[right]]++
//			}else{
//				break
//			}
//		}
//	}
//	return false
//}

//别人写的利用数组作为滑动窗口
//利用数组作为滑动窗口
//func checkInclusion(s1, s2 string) bool {
//	n, m := len(s1), len(s2)
//	if n > m {
//		return false
//	}
//	var cnt1, cnt2 [26]int
//	for i, ch := range s1 {
//		cnt1[ch-'a']++
//		cnt2[s2[i]-'a']++
//	}
//	if cnt1 == cnt2 {
//		return true
//	}
//	for i := n; i < m; i++ {
//		cnt2[s2[i]-'a']++
//		cnt2[s2[i-n]-'a']--
//		if cnt1 == cnt2 {
//			return true
//		}
//	}
//	return false
//}

//自己写的利用数组作为滑动窗口
func checkInclusion(s1, s2 string) bool {
	if len(s1)>len(s2){
		return false
	}

	var m1,m2 [26]int

	for i,j:=range s1{
		m1[j-'a']++     //将0-25这26个数字映射为a-z这26个字母 0对于a 1对应b 以此类推
		m2[s2[i]-'a']++
	}
	if m1==m2{
		return true
	}

	for i:=len(s1);i<len(s2);i++{
		m2[s2[i]-'a']++
		m2[s2[i-len(s1)]-'a']--
		if m1==m2{
			return true
		}
	}
	return false
}

func main() {
	s1:="ab"
	s2:="eidboaoo"
	fmt.Println(checkInclusion(s1,s2))
}
